package com.example.remotecontrol.util

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.wifi.WifiManager
import android.os.Build
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.MediaType.Companion.toMediaType
import org.json.JSONObject
import java.io.IOException
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Socket
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton

/**
 * WiFi管理器
 * 负责WiFi设备的发现和控制
 */
@Singleton
class WiFiManager @Inject constructor(
    private val context: Context
) {
    private val TAG = "WiFiManager"
    
    // OkHttp客户端，用于发送HTTP请求
    private val httpClient = OkHttpClient.Builder()
        .connectTimeout(5, TimeUnit.SECONDS)
        .readTimeout(5, TimeUnit.SECONDS)
        .build()
    
    // WiFi状态
    private val _wifiState = MutableStateFlow<WiFiState>(WiFiState.Unknown)
    val wifiState: StateFlow<WiFiState> = _wifiState.asStateFlow()
    
    // 发现的设备列表
    private val _discoveredDevices = MutableStateFlow<List<WiFiDevice>>(emptyList())
    val discoveredDevices: StateFlow<List<WiFiDevice>> = _discoveredDevices.asStateFlow()
    
    // 网络监听器
    private var networkCallback: ConnectivityManager.NetworkCallback? = null
    
    // 当前连接状态
    private val _connectionState = MutableStateFlow(false)
    val connectionState: StateFlow<Boolean> = _connectionState.asStateFlow()
    
    // 当前连接的主机和端口
    private var connectedHost: String? = null
    private var connectedPort: Int = 0
    
    init {
        // 初始化时检查WiFi状态
        checkWiFiState()
        
        // 注册网络状态监听
        registerNetworkCallback()
    }
    
    /**
     * 检查WiFi是否可用
     */
    fun isWiFiEnabled(): Boolean {
        val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
        return wifiManager.isWifiEnabled
    }
    
    /**
     * 检查当前WiFi连接状态
     */
    fun checkWiFiState() {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        
        val network = connectivityManager.activeNetwork
        if (network == null) {
            _wifiState.value = WiFiState.Disabled
            return
        }
        
        val capabilities = connectivityManager.getNetworkCapabilities(network)
        if (capabilities == null || !capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            _wifiState.value = WiFiState.Disabled
            return
        }
        
        _wifiState.value = WiFiState.Connected
    }
    
    /**
     * 连接到指定主机和端口
     * @param host 目标主机地址
     * @param port 目标端口
     * @return 连接是否成功
     */
    suspend fun connect(host: String, port: Int = 80): Boolean {
        return withContext(Dispatchers.IO) {
            try {
                // 验证WiFi是否可用
                if (_wifiState.value != WiFiState.Connected) {
                    Log.e(TAG, "WiFi not connected")
                    return@withContext false
                }
                
                // 尝试连接Socket（简单测试连通性）
                val socket = Socket()
                socket.connect(InetSocketAddress(host, port), 5000) // 5秒超时
                socket.close()
                
                // 更新连接状态
                connectedHost = host
                connectedPort = port
                _connectionState.value = true
                
                Log.d(TAG, "Successfully connected to $host:$port")
                true
            } catch (e: Exception) {
                Log.e(TAG, "Failed to connect to $host:$port: ${e.message}")
                _connectionState.value = false
                false
            }
        }
    }
    
    /**
     * 发送HTTP请求到设备
     * @param endpoint 端点路径（将添加到主机地址之后）
     * @param payload 要发送的数据
     * @return 响应内容或null（如果失败）
     */
    suspend fun sendHttpRequest(endpoint: String, payload: String): String? {
        val host = connectedHost
        if (host == null || !_connectionState.value) {
            Log.e(TAG, "Not connected to any host")
            return null
        }
        
        return withContext(Dispatchers.IO) {
            try {
                // 构建URL
                val url = "http://$host:$connectedPort/$endpoint".trimEnd('/')
                
                // 构建请求
                val mediaType = "application/json; charset=utf-8".toMediaType()
                val requestBody = payload.toRequestBody(mediaType)
                
                val request = Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build()
                
                // 执行请求
                val response = httpClient.newCall(request).execute()
                
                if (response.isSuccessful) {
                    response.body?.string()
                } else {
                    Log.e(TAG, "HTTP request failed: ${response.code}")
                    null
                }
            } catch (e: Exception) {
                Log.e(TAG, "Failed to send HTTP request: ${e.message}")
                null
            }
        }
    }
    
    /**
     * 发送UDP命令到设备
     * @param command 要发送的命令
     * @param port 目标端口（如果与连接端口不同）
     * @return 是否发送成功
     */
    suspend fun sendUdpCommand(command: String, port: Int = connectedPort): Boolean {
        val host = connectedHost
        if (host == null || !_connectionState.value) {
            Log.e(TAG, "Not connected to any host")
            return false
        }
        
        return withContext(Dispatchers.IO) {
            try {
                val socket = DatagramSocket()
                val address = InetAddress.getByName(host)
                val buf = command.toByteArray()
                val packet = DatagramPacket(buf, buf.size, address, port)
                
                socket.send(packet)
                socket.close()
                
                Log.d(TAG, "UDP command sent successfully to $host:$port")
                true
            } catch (e: Exception) {
                Log.e(TAG, "Failed to send UDP command: ${e.message}")
                false
            }
        }
    }
    
    /**
     * 注册网络状态变化监听
     */
    private fun registerNetworkCallback() {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        
        val request = NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .build()
        
        networkCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                _wifiState.value = WiFiState.Connected
            }
            
            override fun onLost(network: Network) {
                _wifiState.value = WiFiState.Disabled
            }
        }
        
        networkCallback?.let {
            connectivityManager.registerNetworkCallback(request, it)
        }
    }
    
    /**
     * 注销网络状态监听
     */
    fun unregisterNetworkCallback() {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        
        networkCallback?.let {
            try {
                connectivityManager.unregisterNetworkCallback(it)
            } catch (e: Exception) {
                Log.e(TAG, "Failed to unregister network callback: ${e.message}")
            }
        }
    }
    
    /**
     * 发现局域网内的设备
     * 使用SSDP协议（UPnP发现协议）
     */
    suspend fun discoverDevices(): List<WiFiDevice> {
        if (_wifiState.value != WiFiState.Connected) {
            return emptyList()
        }
        
        return withContext(Dispatchers.IO) {
            val devices = mutableListOf<WiFiDevice>()
            
            try {
                // 使用SSDP协议发现设备
                val socket = DatagramSocket()
                socket.soTimeout = 3000 // 3秒超时
                
                // SSDP发现请求
                val ssdpRequest = """
                    M-SEARCH * HTTP/1.1
                    HOST: 239.255.255.250:1900
                    MAN: "ssdp:discover"
                    MX: 3
                    ST: ssdp:all
                    
                """.trimIndent().replace("\n", "\r\n")
                
                val requestData = ssdpRequest.toByteArray()
                val ssdpAddress = InetAddress.getByName("239.255.255.250")
                val packet = DatagramPacket(requestData, requestData.size, ssdpAddress, 1900)
                
                // 发送请求
                socket.send(packet)
                
                // 接收响应
                val buffer = ByteArray(1024)
                val responsePacket = DatagramPacket(buffer, buffer.size)
                
                // 循环接收多个响应
                repeat(10) {
                    try {
                        socket.receive(responsePacket)
                        val response = String(responsePacket.data, 0, responsePacket.length)
                        
                        // 解析响应获取设备信息
                        val device = parseSSPDResponse(response, responsePacket.address)
                        device?.let { devices.add(it) }
                    } catch (e: IOException) {
                        // 超时或读取错误，继续下一个
                        Log.d(TAG, "SSDP receive timeout or error: ${e.message}")
                    }
                }
                
                socket.close()
            } catch (e: Exception) {
                Log.e(TAG, "Error discovering devices: ${e.message}")
            }
            
            // 更新已发现设备列表
            val uniqueDevices = devices.distinctBy { it.id }
            _discoveredDevices.value = uniqueDevices
            uniqueDevices
        }
    }
    
    /**
     * 解析SSDP响应
     */
    private fun parseSSPDResponse(response: String, address: InetAddress): WiFiDevice? {
        try {
            // 从响应中提取设备信息
            // 注意：这是简化的实现，实际上需要进一步请求设备描述文档
            
            val locationMatch = Regex("LOCATION: (http://.*)")
                .find(response)?.groupValues?.getOrNull(1)
            
            val serverMatch = Regex("SERVER: (.*)")
                .find(response)?.groupValues?.getOrNull(1)
            
            val stMatch = Regex("ST: (.*)")
                .find(response)?.groupValues?.getOrNull(1)
            
            val usnMatch = Regex("USN: (.*)")
                .find(response)?.groupValues?.getOrNull(1)
            
            // 设备类型检测
            val deviceType = when {
                stMatch?.contains("roku") == true -> WiFiDeviceType.ROKU
                stMatch?.contains("smarttv") == true -> WiFiDeviceType.SMART_TV
                stMatch?.contains("homekit") == true -> WiFiDeviceType.HOMEKIT
                stMatch?.contains("philips") == true -> WiFiDeviceType.PHILIPS_HUE
                stMatch?.contains("google") == true -> WiFiDeviceType.GOOGLE_HOME
                stMatch?.contains("amazon") == true -> WiFiDeviceType.AMAZON_ECHO
                else -> WiFiDeviceType.GENERIC
            }
            
            return WiFiDevice(
                id = usnMatch ?: address.hostAddress ?: "unknown",
                name = serverMatch ?: "Unknown Device",
                type = deviceType,
                ipAddress = address.hostAddress ?: "unknown",
                controlUrl = locationMatch,
                extraInfo = response
            )
        } catch (e: Exception) {
            Log.e(TAG, "Error parsing SSDP response: ${e.message}")
            return null
        }
    }
    
    /**
     * 发送HTTP请求控制设备
     * @param url 控制URL
     * @param data JSON命令数据
     */
    suspend fun sendHttpCommand(url: String, data: JSONObject): Boolean {
        return withContext(Dispatchers.IO) {
            try {
                val mediaType = "application/json; charset=utf-8".toMediaType()
                val requestBody = data.toString().toRequestBody(mediaType)
                
                val request = Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build()
                
                val response = httpClient.newCall(request).execute()
                
                Log.d(TAG, "Command response: ${response.code} - ${response.body?.string()}")
                response.isSuccessful
            } catch (e: Exception) {
                Log.e(TAG, "Failed to send HTTP command: ${e.message}")
                false
            }
        }
    }
    
    /**
     * WiFi连接状态
     */
    sealed class WiFiState {
        object Unknown : WiFiState()
        object Disabled : WiFiState()
        object Connected : WiFiState()
    }
}

/**
 * WiFi设备类型
 */
enum class WiFiDeviceType {
    GENERIC,
    SMART_TV,
    GOOGLE_HOME,
    AMAZON_ECHO,
    ROKU,
    PHILIPS_HUE,
    HOMEKIT
}

/**
 * WiFi设备信息
 */
data class WiFiDevice(
    val id: String,
    val name: String,
    val type: WiFiDeviceType,
    val ipAddress: String,
    val controlUrl: String? = null,
    val extraInfo: String? = null
) 